From 4baf7c3ea99eedeb681ffbb50a61357b3aa05d0d Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Tue, 16 Dec 2003 15:55:22 +0000 Subject: [PATCH] bitkeeper revision 1.649 (3fdf2aeaeVXAAcKlXMdFTCQuwOYD_g) xl_vbd.c, xl_block.h, xl_block.c: Fixes to Xenolinux blkdev code. --- .../arch/xeno/drivers/block/xl_block.c | 170 +++--- .../arch/xeno/drivers/block/xl_block.h | 4 +- .../arch/xeno/drivers/block/xl_vbd.c | 492 ++++++++---------- 3 files changed, 312 insertions(+), 354 deletions(-) diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c index 23f445515c..de71199c02 100644 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c @@ -58,7 +58,7 @@ static inline void signal_requests_to_xen(void) static inline xl_disk_t *xldev_to_xldisk(kdev_t xldev) { - struct gendisk *gd = xldev_to_gendisk(xldev); + struct gendisk *gd = get_gendisk(xldev); return (xl_disk_t *)gd->real_devices + (MINOR(xldev) >> gd->minor_shift); } @@ -67,26 +67,37 @@ static inline xl_disk_t *xldev_to_xldisk(kdev_t xldev) int xenolinux_block_open(struct inode *inode, struct file *filep) { short xldev = inode->i_rdev; - struct gendisk *gd = xldev_to_gendisk(xldev); + struct gendisk *gd = get_gendisk(xldev); xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev); short minor = MINOR(xldev); - if(!gd->part[minor].nr_sects) { - /* Device either doesn't exist, or has zero capacity; we use - a few cheesy heuristics to return the relevant error code */ - if(disk->capacity || (minor & (gd->max_p - 1))) { - // we have a real device, but no such partition, or we just - // have a partition number so guess this is the problem - return -ENXIO; // no such device or address - } else if (gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE) { - // this is a removable device => assume that media is missing - return -ENOMEDIUM; // media not present (this is a guess) - } else - // just go for the general 'no such device' error - return -ENODEV; // no such device + if ( gd->part[minor].nr_sects == 0 ) + { + /* + * Device either doesn't exist, or has zero capacity; we use a few + * cheesy heuristics to return the relevant error code + */ + if ( (gd->sizes[minor >> gd->minor_shift] != 0) || + ((minor & (gd->max_p - 1)) != 0) ) + { + /* + * We have a real device, but no such partition, or we just have a + * partition number so guess this is the problem. + */ + return -ENXIO; /* no such device or address */ + } + else if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE ) + { + /* This is a removable device => assume that media is missing. */ + return -ENOMEDIUM; /* media not present (this is a guess) */ + } + else + { + /* Just go for the general 'no such device' error. */ + return -ENODEV; /* no such device */ + } } - disk->usage++; DPRINTK("xenolinux_block_open\n"); return 0; @@ -103,7 +114,7 @@ int xenolinux_block_release(struct inode *inode, struct file *filep) int xenolinux_block_ioctl(struct inode *inode, struct file *filep, - unsigned command, unsigned long argument) + unsigned command, unsigned long argument) { kdev_t dev = inode->i_rdev; struct hd_geometry *geo = (struct hd_geometry *)argument; @@ -115,21 +126,21 @@ int xenolinux_block_ioctl(struct inode *inode, struct file *filep, DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n", command, (long) argument, dev); - gd = xldev_to_gendisk(dev); + gd = get_gendisk(dev); part = &gd->part[MINOR(dev)]; switch ( command ) { case BLKGETSIZE: DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects); - return put_user(part->nr_sects, (unsigned long *) argument); + return put_user(part->nr_sects, (unsigned long *) argument); case BLKRRPART: /* re-read partition table */ DPRINTK_IOCTL(" BLKRRPART: %x\n", BLKRRPART); return xenolinux_block_revalidate(dev); case BLKSSZGET: - return hardsect_size[MAJOR(dev)][MINOR(dev)]; + return hardsect_size[MAJOR(dev)][MINOR(dev)]; case BLKBSZGET: /* get block size */ DPRINTK_IOCTL(" BLKBSZGET: %x\n", BLKBSZGET); @@ -137,35 +148,35 @@ int xenolinux_block_ioctl(struct inode *inode, struct file *filep, case BLKBSZSET: /* set block size */ DPRINTK_IOCTL(" BLKBSZSET: %x\n", BLKBSZSET); - break; + break; case BLKRASET: /* set read-ahead */ DPRINTK_IOCTL(" BLKRASET: %x\n", BLKRASET); - break; + break; case BLKRAGET: /* get read-ahead */ DPRINTK_IOCTL(" BLKRAFET: %x\n", BLKRAGET); - break; + break; case HDIO_GETGEO: /* note: these values are complete garbage */ DPRINTK_IOCTL(" HDIO_GETGEO: %x\n", HDIO_GETGEO); - if (!argument) return -EINVAL; - if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT; - if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT; - if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT; - if (put_user(0x106, (unsigned short *)&geo->cylinders)) return -EFAULT; - return 0; + if (!argument) return -EINVAL; + if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT; + if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT; + if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT; + if (put_user(0x106, (unsigned short *)&geo->cylinders)) return -EFAULT; + return 0; case HDIO_GETGEO_BIG: /* note: these values are complete garbage */ DPRINTK_IOCTL(" HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG); - if (!argument) return -EINVAL; - if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT; - if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT; - if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT; - if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT; - return 0; + if (!argument) return -EINVAL; + if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT; + if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT; + if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT; + if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT; + return 0; case CDROMMULTISESSION: DPRINTK("FIXME: support multisession CDs later\n"); @@ -175,7 +186,7 @@ int xenolinux_block_ioctl(struct inode *inode, struct file *filep, default: printk("ioctl %08x not supported by xl_block\n", command); - return -ENOSYS; + return -ENOSYS; } return 0; @@ -190,13 +201,20 @@ int xenolinux_block_check(kdev_t dev) int xenolinux_block_revalidate(kdev_t dev) { - struct gendisk *gd = xldev_to_gendisk(dev); + struct gendisk *gd = get_gendisk(dev); xl_disk_t *disk = xldev_to_xldisk(dev); - unsigned long flags; + unsigned long flags, capacity = gd->part[MINOR(dev)].nr_sects; int i, disk_nr = MINOR(dev) >> gd->minor_shift; DPRINTK("xenolinux_block_revalidate: %d\n", dev); + /* + * We didn't construct this VBD by reading a partition table. This + * function can only do bad things to us. + */ + if ( capacity == 0 ) + return -EINVAL; + spin_lock_irqsave(&io_request_lock, flags); if ( disk->usage > 1 ) { @@ -212,27 +230,9 @@ int xenolinux_block_revalidate(kdev_t dev) gd->part[MINOR(dev+i)].nr_sects = 0; } -#if 0 - /* VBDs can change under our feet. Check if that has happened. */ - if ( MAJOR(dev) == XLVIRT_MAJOR ) - { - xen_disk_info_t *xdi = kmalloc(sizeof(*xdi), GFP_KERNEL); - if ( xdi != NULL ) - { - memset(xdi, 0, sizeof(*xdi)); - xenolinux_control_msg(XEN_BLOCK_PROBE, - (char *)xdi, sizeof(*xdi)); - for ( i = 0; i < xdi->count; i++ ) - if ( IS_VIRTUAL_XENDEV(xdi->disks[i].device) && - ((xdi->disks[i].device & XENDEV_IDX_MASK) == disk_nr) ) - ((xl_disk_t *)gd->real_devices)[disk_nr].capacity = - xdi->disks[i].capacity; - kfree(xdi); - } - } -#endif + /* XXX Should perhaps revalidate VBDs here */ - grok_partitions(gd, disk_nr, gd->nr_real, disk->capacity); + grok_partitions(gd, disk_nr, gd->nr_real, capacity); return 0; } @@ -271,14 +271,12 @@ static int hypervisor_request(unsigned long id, case XEN_BLOCK_READ: case XEN_BLOCK_WRITE: + gd = get_gendisk(device); - /* Get the appropriate gendisk */ - gd = xldev_to_gendisk(device); - - /* Update the sector_number we'll pass down as appropriate; note - that we could sanity check that resulting sector will be in - this partition, but this will happen in xen anyhow */ - sector_number += gd->part[MINOR(device)].start_sect; + /* Update the sector_number we'll pass down as appropriate; note + that we could sanity check that resulting sector will be in + this partition, but this will happen in xen anyhow */ + sector_number += gd->part[MINOR(device)].start_sect; if ( (sg_operation == operation) && (sg_dev == device) && @@ -339,9 +337,9 @@ void do_xlblk_request(request_queue_t *rq) while ( !rq->plugged && !list_empty(&rq->queue_head)) { - if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL ) - goto out; - + if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL ) + goto out; + DPRINTK("do_xlblk_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n", req, req->cmd, req->sector, req->current_nr_sectors, req->nr_sectors, req->bh); @@ -351,11 +349,11 @@ void do_xlblk_request(request_queue_t *rq) if ((rw != READ) && (rw != WRITE)) panic("XenoLinux Virtual Block Device: bad cmd: %d\n", rw); - req->errors = 0; + req->errors = 0; bh = req->bh; while ( bh != NULL ) - { + { next_bh = bh->b_reqnext; bh->b_reqnext = NULL; @@ -364,12 +362,12 @@ void do_xlblk_request(request_queue_t *rq) (rw == READ) ? XEN_BLOCK_READ : XEN_BLOCK_WRITE, bh->b_data, bh->b_rsector, bh->b_size>>9, bh->b_rdev); - if(full) { + if(full) { - bh->b_reqnext = next_bh; - pending_queues[nr_pending++] = rq; - if ( nr_pending >= MAX_PENDING ) BUG(); - goto out; + bh->b_reqnext = next_bh; + pending_queues[nr_pending++] = rq; + if ( nr_pending >= MAX_PENDING ) BUG(); + goto out; } @@ -430,15 +428,15 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs) if ( state == STATE_CLOSED ) return; - spin_lock_irqsave(&io_request_lock, flags); + spin_lock_irqsave(&io_request_lock, flags); for ( i = resp_cons; - i != blk_ring->resp_prod; - i = BLK_RING_INC(i) ) + i != blk_ring->resp_prod; + i = BLK_RING_INC(i) ) { - blk_ring_resp_entry_t *bret = &blk_ring->ring[i].resp; - switch (bret->operation) - { + blk_ring_resp_entry_t *bret = &blk_ring->ring[i].resp; + switch (bret->operation) + { case XEN_BLOCK_READ: case XEN_BLOCK_WRITE: if ( bret->status ) @@ -452,11 +450,11 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs) bh->b_reqnext = NULL; bh->b_end_io(bh, !bret->status); } - break; - + break; + default: BUG(); - } + } } resp_cons = i; @@ -501,8 +499,8 @@ int __init xlblk_init(void) SA_SAMPLE_RANDOM, "blkdev", NULL); if ( error ) { - printk(KERN_ALERT "Could not allocate receive interrupt\n"); - goto fail; + printk(KERN_ALERT "Could not allocate receive interrupt\n"); + goto fail; } /* Setup our [empty] disk information structure */ diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h index 8fcaa59383..c4cd7ec44e 100644 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h @@ -47,7 +47,6 @@ */ typedef struct xl_disk { int usage; - unsigned long capacity; } xl_disk_t; /* Generic layer. */ @@ -55,7 +54,7 @@ extern int xenolinux_control_msg(int operration, char *buffer, int size); extern int xenolinux_block_open(struct inode *inode, struct file *filep); extern int xenolinux_block_release(struct inode *inode, struct file *filep); extern int xenolinux_block_ioctl(struct inode *inode, struct file *filep, - unsigned command, unsigned long argument); + unsigned command, unsigned long argument); extern int xenolinux_block_check(kdev_t dev); extern int xenolinux_block_revalidate(kdev_t dev); extern void do_xlblk_request (request_queue_t *rq); @@ -64,6 +63,5 @@ extern void do_xlblk_request (request_queue_t *rq); /* Virtual block-device subsystem. */ extern int xlvbd_init(xen_disk_info_t *xdi); extern void xlvbd_cleanup(void); -extern struct gendisk *xldev_to_gendisk(kdev_t xldev); #endif /* __XL_BLOCK_H__ */ diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c index 386162e9f3..2b65705083 100644 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c @@ -6,16 +6,9 @@ */ #include "xl_block.h" - -// #define MAJOR_NR XLVIRT_MAJOR #include -/* Copied from linux/ide.h */ -typedef unsigned char byte; - -#define XLVBD_MAX_MAJORS 64 /* total number of vbds we support */ - -struct gendisk *xlvbd_gendisk[XLVBD_MAX_MAJORS] = { NULL }; +#define GENHD_FL_XENO 2 /* For convenience we distinguish between ide, scsi and 'other' (i.e. ** potentially combinations of the two) in the naming scheme and in a @@ -29,7 +22,6 @@ struct gendisk *xlvbd_gendisk[XLVBD_MAX_MAJORS] = { NULL }; #define XLSCSI_DEVS_PER_MAJOR 16 #define XLVBD_DEVS_PER_MAJOR 16 - #define XLIDE_PARTN_SHIFT 6 /* amount to shift minor to get 'real' minor */ #define XLIDE_MAX_PART (1 << XLIDE_PARTN_SHIFT) /* minors per ide vbd */ @@ -39,7 +31,6 @@ struct gendisk *xlvbd_gendisk[XLVBD_MAX_MAJORS] = { NULL }; #define XLVBD_PARTN_SHIFT 6 /* amount to shift minor to get 'real' minor */ #define XLVBD_MAX_PART (1 << XLVBD_PARTN_SHIFT) /* minors per 'other' vbd */ - /* the below are for the use of the generic drivers/block/ll_rw_block.c code */ static int xlide_blksize_size[256]; static int xlide_hardsect_size[256]; @@ -51,7 +42,6 @@ static int xlvbd_blksize_size[256]; static int xlvbd_hardsect_size[256]; static int xlvbd_max_sectors[256]; - static struct block_device_operations xlvbd_block_fops = { open: xenolinux_block_open, @@ -61,290 +51,262 @@ static struct block_device_operations xlvbd_block_fops = revalidate: xenolinux_block_revalidate, }; - -typedef unsigned char bool; - -/* -** Set up all the linux device goop for the virtual block devices (vbd's) -** that xen tells us about. Note that although from xen's pov VBDs are -** addressed simply an opaque 16-bit device number, the domain creation -** tools conventionally allocate these numbers to correspond to those -** used by 'real' linux -- this is just for convenience as it means e.g. -** that the same /etc/fstab can be used when booting with or without xen. -*/ +/* + * Set up all the linux device goop for the virtual block devices (vbd's) that + * xen tells us about. Note that although from xen's pov VBDs are addressed + * simply an opaque 16-bit device number, the domain creation tools + * conventionally allocate these numbers to correspond to those used by 'real' + * linux -- this is just for convenience as it means e.g. that the same + * /etc/fstab can be used when booting with or without xen. + */ int __init xlvbd_init(xen_disk_info_t *xdi) { int i, result, max_part; struct gendisk *gd = NULL; kdev_t device; unsigned short major, minor, partno; - bool is_ide, is_scsi; + int is_ide, is_scsi; char *major_name; unsigned char buf[64]; - int majors[256]; SET_MODULE_OWNER(&xlvbd_block_fops); /* Initialize the global arrays. */ - for (i = 0; i < 256; i++) + for ( i = 0; i < 256; i++ ) { - /* from the generic ide code (drivers/ide/ide-probe.c, etc) */ - xlide_blksize_size[i] = 1024; - xlide_hardsect_size[i] = 512; - xlide_max_sectors[i] = 128; /* 'hwif->rqsize' if we knew it */ - - /* from the generic scsi disk code (drivers/scsi/sd.c) */ - xlscsi_blksize_size[i] = 1024; //XXX 512; - xlscsi_hardsect_size[i] = 512; - xlscsi_max_sectors[i] = 128*8; //XXX 128; - - /* we don't really know what to set these too since it depends */ - xlvbd_blksize_size[i] = 512; - xlvbd_hardsect_size[i] = 512; - xlvbd_max_sectors[i] = 128; + /* from the generic ide code (drivers/ide/ide-probe.c, etc) */ + xlide_blksize_size[i] = 1024; + xlide_hardsect_size[i] = 512; + xlide_max_sectors[i] = 128; /* 'hwif->rqsize' if we knew it */ + + /* from the generic scsi disk code (drivers/scsi/sd.c) */ + xlscsi_blksize_size[i] = 1024; /* XXX 512; */ + xlscsi_hardsect_size[i] = 512; + xlscsi_max_sectors[i] = 128*8; /* XXX 128; */ + + /* we don't really know what to set these too since it depends */ + xlvbd_blksize_size[i] = 512; + xlvbd_hardsect_size[i] = 512; + xlvbd_max_sectors[i] = 128; } - - /* keep track of which majors we've seen so far */ - for (i = 0; i < 256; i++) - majors[i] = 0; - - /* - ** We need to loop through each major device we've been told about and: - ** a) register the appropriate blkdev - ** b) setup the indexed-by-major global arrays (blk_size[], - ** blksize_size[], hardsect_size[], max_sectors[], read_ahead[]) - ** c) setup the block queue + make it sensible - ** d) create an appropriate gendisk structure, and - ** e) register the gendisk - */ - for (i = 0; i < xdi->count; i++) + /* + * We need to loop through each major device we've been told about and: + * a) register the appropriate blkdev + * b) setup the indexed-by-major global arrays (blk_size[], + * blksize_size[], hardsect_size[], max_sectors[], read_ahead[]) + * c) setup the block queue + make it sensible + * d) create an appropriate gendisk structure, and + * e) register the gendisk + */ + for ( i = 0; i < xdi->count; i++ ) { - device = xdi->disks[i].device; - major = MAJOR(device); - minor = MINOR(device); - is_ide = IDE_DISK_MAJOR(major); /* is this an ide device? */ - is_scsi= SCSI_BLK_MAJOR(major); /* is this a scsi device? */ - - if(is_ide) { - major_name = XLIDE_MAJOR_NAME; - max_part = XLIDE_MAX_PART; - } else if(is_scsi) { - major_name = XLSCSI_MAJOR_NAME; - max_part = XLSCSI_MAX_PART; - } else { - major_name = XLVBD_MAJOR_NAME; - max_part = XLVBD_MAX_PART; - } - - /* - ** XXX SMH: conventionally we assume a minor device if the - ** corresponding linux device number would be a minor device; - ** minor devices require slightly different handling than - ** 'full' devices (e.g. in terms of partition table handling). - */ - partno = minor & (max_part - 1); - - if(!majors[major]) { - - result = register_blkdev(major, major_name, &xlvbd_block_fops); - if (result < 0) { - printk(KERN_ALERT "XL VBD: can't get major %d\n", major); - continue; - } - - blk_size[major] = NULL; - if(is_ide) { - blksize_size[major] = xlide_blksize_size; - hardsect_size[major] = xlide_hardsect_size; - max_sectors[major] = xlide_max_sectors; - read_ahead[major] = 8; // from drivers/ide/ide-probe.c - } else if(is_scsi) { - blksize_size[major] = xlscsi_blksize_size; - hardsect_size[major] = xlscsi_hardsect_size; - max_sectors[major] = xlscsi_max_sectors; - read_ahead[major] = 0; // XXX 8; -- guessing - } else { - blksize_size[major] = xlvbd_blksize_size; - hardsect_size[major] = xlvbd_hardsect_size; - max_sectors[major] = xlvbd_max_sectors; - read_ahead[major] = 8; - } - - blk_init_queue(BLK_DEFAULT_QUEUE(major), do_xlblk_request); - - /* - * Turn off barking 'headactive' mode. We dequeue buffer heads as - * soon as we pass them down to Xen. - */ - blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0); - - /* Construct an appropriate gendisk structure. */ - gd = kmalloc(sizeof(struct gendisk), GFP_KERNEL); - gd->major = major; - gd->major_name = major_name; - - gd->max_p = max_part; - if(is_ide) { - gd->minor_shift = XLIDE_PARTN_SHIFT; - gd->nr_real = XLIDE_DEVS_PER_MAJOR; - } else if(is_scsi) { - gd->minor_shift = XLSCSI_PARTN_SHIFT; - gd->nr_real = XLSCSI_DEVS_PER_MAJOR; - } else { - gd->minor_shift = XLVBD_PARTN_SHIFT; - gd->nr_real = XLVBD_DEVS_PER_MAJOR; - } - - /* - ** The sizes[] and part[] arrays hold the sizes and other - ** information about every partition with this 'major' (i.e. - ** every disk sharing the 8 bit prefix * max partns per disk) - */ - gd->sizes = kmalloc(max_part*gd->nr_real*sizeof(int), GFP_KERNEL); - gd->part = kmalloc(max_part*gd->nr_real*sizeof(struct hd_struct), - GFP_KERNEL); - memset(gd->sizes, 0, max_part * gd->nr_real * sizeof(int)); - memset(gd->part, 0, max_part * gd->nr_real - * sizeof(struct hd_struct)); - - - gd->real_devices = kmalloc(gd->nr_real * sizeof(xl_disk_t), - GFP_KERNEL); - memset(gd->real_devices, 0, gd->nr_real * sizeof(xl_disk_t)); - - gd->next = NULL; - gd->fops = &xlvbd_block_fops; - - gd->de_arr = kmalloc(gd->nr_real * sizeof(*gd->de_arr), - GFP_KERNEL); - gd->flags = kmalloc(gd->nr_real * sizeof(*gd->flags), GFP_KERNEL); - - memset(gd->de_arr, 0, gd->nr_real * sizeof(*gd->de_arr)); - memset(gd->flags, 0, gd->nr_real * sizeof(*gd->flags)); - - /* - ** Keep track of gendisk both locally and in the global array. - ** XXX SMH: can probably do without local copy -- FIXME later - */ - xlvbd_gendisk[i] = gd; - add_gendisk(gd); - - /* XXX SMH: not clear on what 'real_devices' is indexed by; - hence using unit number for now but in old code was 'disk' aka - sequence number assigned by xen during probe = barfle? */ - ((xl_disk_t *)gd->real_devices)[minor>>gd->minor_shift].capacity = - xdi->disks[i].capacity; - - - /* remember that we've done this major */ - majors[major] = 1; - } else - /* Continue the setup of this gendisk */ - gd = get_gendisk(device); - - if(XD_READONLY(xdi->disks[i].info)) - set_device_ro(device, 1); - - if(partno) { - - /* Need to skankily setup 'partition' information */ - gd->part[partno].start_sect = 0; - gd->part[partno].nr_sects = xdi->disks[i].capacity; - gd->sizes[partno] = xdi->disks[i].capacity; - - } else { - - /* Some final fix-ups depending on the device type */ - switch (XD_TYPE(xdi->disks[i].info)) - { - - case XD_TYPE_CDROM: - case XD_TYPE_FLOPPY: - case XD_TYPE_TAPE: - gd->flags[minor >> gd->minor_shift] = GENHD_FL_REMOVABLE; - printk(KERN_ALERT - "Skipping partition check on %s /dev/%s\n", - XD_TYPE(xdi->disks[i].info)==XD_TYPE_CDROM ? "cdrom" : - (XD_TYPE(xdi->disks[i].info)==XD_TYPE_TAPE ? "tape" : - "floppy"), disk_name(gd, MINOR(device), buf)); - break; - - case XD_TYPE_DISK: - register_disk(gd, device, gd->nr_real, &xlvbd_block_fops, - xdi->disks[i].capacity); - break; - - default: - printk(KERN_ALERT "XenoLinux: unknown device type %d\n", - XD_TYPE(xdi->disks[i].info)); - break; - } - - } - - printk(KERN_ALERT "XenoLinux Virtual Block Device Driver " - "installed [device: %04x]\n", device); + device = xdi->disks[i].device; + major = MAJOR(device); + minor = MINOR(device); + is_ide = IDE_DISK_MAJOR(major); /* is this an ide device? */ + is_scsi= SCSI_BLK_MAJOR(major); /* is this a scsi device? */ + + if ( is_ide ) + { + major_name = XLIDE_MAJOR_NAME; + max_part = XLIDE_MAX_PART; + } + else if ( is_scsi ) + { + major_name = XLSCSI_MAJOR_NAME; + max_part = XLSCSI_MAX_PART; + } + else + { + major_name = XLVBD_MAJOR_NAME; + max_part = XLVBD_MAX_PART; + } + + partno = minor & (max_part - 1); + + if ( (gd = get_gendisk(device)) == NULL ) + { + result = register_blkdev(major, major_name, &xlvbd_block_fops); + if ( result < 0 ) + { + printk(KERN_ALERT "XL VBD: can't get major %d\n", major); + continue; + } + + if( is_ide ) + { + blksize_size[major] = xlide_blksize_size; + hardsect_size[major] = xlide_hardsect_size; + max_sectors[major] = xlide_max_sectors; + read_ahead[major] = 8; /* from drivers/ide/ide-probe.c */ + } + else if ( is_scsi ) + { + blksize_size[major] = xlscsi_blksize_size; + hardsect_size[major] = xlscsi_hardsect_size; + max_sectors[major] = xlscsi_max_sectors; + read_ahead[major] = 0; /* XXX 8; -- guessing */ + } + else + { + blksize_size[major] = xlvbd_blksize_size; + hardsect_size[major] = xlvbd_hardsect_size; + max_sectors[major] = xlvbd_max_sectors; + read_ahead[major] = 8; + } + + blk_init_queue(BLK_DEFAULT_QUEUE(major), do_xlblk_request); + + /* + * Turn off barking 'headactive' mode. We dequeue buffer heads as + * soon as we pass them down to Xen. + */ + blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0); + + /* Construct an appropriate gendisk structure. */ + gd = kmalloc(sizeof(struct gendisk), GFP_KERNEL); + gd->major = major; + gd->major_name = major_name; + + gd->max_p = max_part; + if ( is_ide ) + { + gd->minor_shift = XLIDE_PARTN_SHIFT; + gd->nr_real = XLIDE_DEVS_PER_MAJOR; + } + else if ( is_scsi ) + { + gd->minor_shift = XLSCSI_PARTN_SHIFT; + gd->nr_real = XLSCSI_DEVS_PER_MAJOR; + } + else + { + gd->minor_shift = XLVBD_PARTN_SHIFT; + gd->nr_real = XLVBD_DEVS_PER_MAJOR; + } + + /* + ** The sizes[] and part[] arrays hold the sizes and other + ** information about every partition with this 'major' (i.e. + ** every disk sharing the 8 bit prefix * max partns per disk) + */ + gd->sizes = kmalloc(max_part*gd->nr_real*sizeof(int), GFP_KERNEL); + gd->part = kmalloc(max_part*gd->nr_real*sizeof(struct hd_struct), + GFP_KERNEL); + memset(gd->sizes, 0, max_part * gd->nr_real * sizeof(int)); + memset(gd->part, 0, max_part * gd->nr_real + * sizeof(struct hd_struct)); + + + gd->real_devices = kmalloc(gd->nr_real * sizeof(xl_disk_t), + GFP_KERNEL); + memset(gd->real_devices, 0, gd->nr_real * sizeof(xl_disk_t)); + + gd->next = NULL; + gd->fops = &xlvbd_block_fops; + + gd->de_arr = kmalloc(gd->nr_real * sizeof(*gd->de_arr), + GFP_KERNEL); + gd->flags = kmalloc(gd->nr_real * sizeof(*gd->flags), GFP_KERNEL); + + memset(gd->de_arr, 0, gd->nr_real * sizeof(*gd->de_arr)); + memset(gd->flags, 0, gd->nr_real * sizeof(*gd->flags)); + + add_gendisk(gd); + + blk_size[major] = gd->sizes; + } + + if ( XD_READONLY(xdi->disks[i].info) ) + set_device_ro(device, 1); + + gd->flags[minor >> gd->minor_shift] |= GENHD_FL_XENO; + + if ( partno != 0 ) + { + /* Need to skankily setup 'partition' information */ + gd->part[partno].start_sect = 0; + gd->part[partno].nr_sects = xdi->disks[i].capacity; + gd->sizes[partno] = xdi->disks[i].capacity; + } + else + { + /* Some final fix-ups depending on the device type */ + switch ( XD_TYPE(xdi->disks[i].info) ) + { + case XD_TYPE_CDROM: + case XD_TYPE_FLOPPY: + case XD_TYPE_TAPE: + gd->part[minor].nr_sects = xdi->disks[i].capacity; + gd->sizes[minor] = xdi->disks[i].capacity>>(BLOCK_SIZE_BITS-9); + gd->flags[minor >> gd->minor_shift] |= GENHD_FL_REMOVABLE; + printk(KERN_ALERT + "Skipping partition check on %s /dev/%s\n", + XD_TYPE(xdi->disks[i].info)==XD_TYPE_CDROM ? "cdrom" : + (XD_TYPE(xdi->disks[i].info)==XD_TYPE_TAPE ? "tape" : + "floppy"), disk_name(gd, MINOR(device), buf)); + break; + + case XD_TYPE_DISK: + register_disk(gd, device, gd->nr_real, &xlvbd_block_fops, + xdi->disks[i].capacity); + break; + + default: + printk(KERN_ALERT "XenoLinux: unknown device type %d\n", + XD_TYPE(xdi->disks[i].info)); + break; + } + } + + printk(KERN_ALERT "XenoLinux Virtual Block Device Driver " + "installed [device: %04x]\n", device); } return 0; } -/* -** XXX SMH: crappy linear scan routine to map from a device number bac k -** to the relevant gendisk; could be made better if and when it becomes -** an issue but for now we expect success within a few loop iterations. -*/ -struct gendisk *xldev_to_gendisk(kdev_t xldev) -{ - int i; - short major = MAJOR(xldev); - - for(i = 0; i < XLVBD_MAX_MAJORS; i++) { - if(xlvbd_gendisk[i]->major == major) - return xlvbd_gendisk[i]; - } - - /* didn't find it -- death */ - BUG(); - return NULL; -} - void xlvbd_cleanup(void) { - bool is_ide, is_scsi; + int is_ide, is_scsi, i; struct gendisk *gd; char *major_name; int major; - for(major = 0; major < XLVBD_MAX_MAJORS; major++) { - - if(!(gd = xlvbd_gendisk[major])) - continue; - - is_ide = IDE_DISK_MAJOR(major); /* is this an ide device? */ - is_scsi= SCSI_BLK_MAJOR(major); /* is this a scsi device? */ - - blk_cleanup_queue(BLK_DEFAULT_QUEUE(major)); - - if(is_ide) { - major_name = XLIDE_MAJOR_NAME; - } else if(is_scsi) { - major_name = XLSCSI_MAJOR_NAME; - } else { - major_name = XLVBD_MAJOR_NAME; - } - - if (unregister_blkdev(major, major_name) != 0) - printk(KERN_ALERT "XenoLinux Virtual Block Device Driver:" - "major device %04x uninstalled w/ errors\n", major); - + for ( major = 0; major < MAX_BLKDEV; major++ ) + { + if ( (gd = get_gendisk(MKDEV(major, 0))) == NULL ) + continue; + + /* + * If this is a 'Xeno' blkdev then at least one unit will have the Xeno + * flag set. + */ + for ( i = 0; i < gd->nr_real; i++ ) + if ( gd->flags[i] & GENHD_FL_XENO ) + break; + if ( i == gd->nr_real ) + continue; + + is_ide = IDE_DISK_MAJOR(major); /* is this an ide device? */ + is_scsi = SCSI_BLK_MAJOR(major); /* is this a scsi device? */ + + blk_cleanup_queue(BLK_DEFAULT_QUEUE(major)); + + if ( is_ide ) + major_name = XLIDE_MAJOR_NAME; + else if ( is_scsi ) + major_name = XLSCSI_MAJOR_NAME; + else + major_name = XLVBD_MAJOR_NAME; + + if ( unregister_blkdev(major, major_name) != 0 ) + printk(KERN_ALERT "XenoLinux Virtual Block Device Driver:" + "major device %04x uninstalled w/ errors\n", major); } - - return; } - #ifdef MODULE module_init(xlvbd_init); module_exit(xlvbd_cleanup); -- 2.30.2